<template>
    <div class="upload-file">
        <div class="paste_div" v-if="isType && isBigVideo && size != 'smaller'">
            <el-input v-on:paste="handlePaste"
                :class="{ paste_input: true, sizeinput300: size === 'large', sizeinput200: size === 'small' }"
                placeholder="点击粘贴图片" />
        </div>
        <draggable class='dragge_box' :list="fileList" ghost-class="ghost" chosen-class="chosenClass" animation="300"
            @start="onStart" @end="onEnd">
            <template #item="{ element, index }">
                <span class="styleDisplays">
                    <!-- <el-image
                        :class="{ preview: true, size300: size === 'large', size200: size === 'small',size100: size === 'smaller' }"
                        :src="element.url + '?x-oss-process=image/resize,w_300'" fit="fill" /> -->
                    <el-image v-if="isType" class="delete" :src="icon_shanchu" @click="handleDelete(index)"></el-image>
                    <div class="styleDisplays_items">
                        上传成功
                    </div>
                </span>
            </template>
        </draggable>
        <el-upload action="#" multiple :limit="limit" :show-file-list="false" :on-exceed="handleExceed"
            v-loading.lock="isLoading" :before-upload="handleBeforeUpload" :on-success="handleUploadSuccess"
            :on-error="handleUploadError" :file-list="fileList" ref="fileUploadRef" drag
            v-if="isType && fileList.length < limit" :http-request="httpRequest" class="upload_home">
            <div
                :class="{ upload_box: true, size300: size === 'large', size200: size === 'small', size100: size === 'smaller' }">
                <el-icon class="upload_box_icon" :style="{ 'font-size': size == 'smaller' && '30px' }">
                    <UploadFilled />
                </el-icon>
                <div class="upload_box_text" v-if="size != 'smaller'">
                    将文件拖到此处，或 <em>点击上传</em>
                </div>
                <div class="upload_box_tip" v-if="showTip && size != 'smaller'">
                    请上传
                    <template v-if="fileSize">
                        大小不超过 <b style="color: #f56c6c">{{ fileSize }}MB</b>
                    </template>
                    <template v-if="fileType">
                        格式为 <b style="color: #f56c6c">{{ fileType.join("/") }}</b>
                    </template>
                    的文件
                </div>
            </div>
        </el-upload>
        <el-dialog v-model="dialogVisible" title="预览" width="800px" append-to-body>
            <img :src="dialogImageUrl" style="display: block; max-width: 100%; margin: 0 auto" />
        </el-dialog>
    </div>
</template>

<script setup lang="ts">
import { propTypes } from '@/utils/propTypes';
import icon_shanchu from '@/assets/images/icon_shanchu.png'
import icon_quanping from '@/assets/images/icon_quanping.png'
import draggable from 'vuedraggable';
import * as OSS from 'ali-oss';
import { put, getFileNameUUID } from '@/utils/oss'


//拖拽开始的事件
const onStart = () => {
    console.log("开始拖拽");
}
//拖拽结束的事件
const onEnd = () => {
    emit("update:modelValue", getPicByfullPath(fileList.value));
}
const props = defineProps({
    modelValue: [String, Object, Array],
    // 数量限制
    limit: propTypes.number.def(5),
    // 大小限制(MB)
    fileSize: propTypes.number.def(30),
    // 文件类型, 例如['png', 'jpg', 'jpeg']
    fileType: propTypes.array.def(['png', 'jpg', 'jpeg']),
    // 是否显示提示
    isShowTip: propTypes.bool.def(true),
    isType: propTypes.bool.def(true),
    isBigVideo: propTypes.bool.def(true),
    size: propTypes.any.def('large'),
    isImage: propTypes.bool.def(true),
});

const isLoading = ref()
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const emit = defineEmits(['update:modelValue']);
const number = ref(0);
const uploadList = ref<any[]>([]);

const fileList = ref<any[]>([]);
const showTip = computed(
    () => props.isShowTip && (props.fileType || props.fileSize)
);

const dialogImageUrl = ref('');
const dialogVisible = ref(false);

const today = new Date();
const year = today.getFullYear();
const month = today.getMonth() + 1;
const date = today.getDate();

const fileUploadRef = ref<ElUploadInstance>();
watch(
    () => props.modelValue,
    async (val) => {
        if (val) {
            // 首先将值转为数组
            let list: any[] = [];
            if (Array.isArray(val)) {
                list = val as any[];
            } else {
                const real_src = val.split(",");
                list = real_src.map((item: string) => import.meta.env.VITE_APP_PIC_URL + item);
            }
            // 然后将数组转为对象数组
            fileList.value = list.map((item) => {
                // 字符串回显处理 如果此处存的是url可直接回显 如果存的是id需要调用接口查出来
                let itemData;
                if (typeof item === 'string') {
                    var filename: any = item.split('/').pop();
                    var decodedFilename = decodeURIComponent(filename)
                    itemData = { name: decodedFilename, url: item };
                } else {
                    // 此处name使用ossId 防止删除出现重名
                    itemData = { name: item.ossId, url: item.url, ossId: item.ossId };
                }
                return itemData;
            });
        } else {
            fileList.value = [];
            return [];
        }
    },
    { deep: true, immediate: true }
);
// 监听paste事件
const handlePaste = async (evt: any) => {
    if (!isLoading.value) {
        const txt = evt.clipboardData.getData('Text')
        if (typeof txt == 'string' && txt !== '') {
            //检测到是文字，过滤
            proxy?.$modal.msgError(`请粘贴图片!`);
            return
        }
        const files: any[] = []
        const items = (evt.clipboardData || (window as any).clipboardData).items
        if (!items.length) return
        for (let i = 0; i < items.length; i++) {
            if (items[i].type.indexOf('image') !== -1) {
                const file = items[i].getAsFile()
                if (file) {
                    files.push(file)
                }
            } else {
                proxy?.$modal.msgError(`请粘贴图片!`);
                return
            }
        }
        if (files.length + fileList.value.length > props.limit) {
            proxy?.$modal.msgError(`上传文件数量不能超过${props.limit}个!`);
            return
        }
        for (let i = 0; i < files.length; i++) {
            isLoading.value = true
            try {
                await httpRequest({ file: files[i] })
            } catch (error) {
                isLoading.value = false
                return
            }
            isLoading.value = false
        }
    } else {
        proxy?.$modal.msgError(`正在上传文件，请稍候...`);
    }
}
const httpRequest = async (option: any) => {
    // 获取文件的后缀名
    var obj = option.file.name
    var index = obj.lastIndexOf(".");
    obj = obj.substring(index, obj.length);
    // 生成的文件名，保留文件后缀名，进行拼接      
    let objName = getFileName(option.file.name)
    const data = year + '/' + month + '/' + date
    try {
        const res = await put(`${data}/${getFileNameUUID()}/${objName}`, option.file);
        fileList.value.push({ name: objName, url: res.url });
        emit("update:modelValue", getPicByfullPath(fileList.value));
    } catch (error) {
        console.error('上传失败:', error);
        proxy?.$modal.msgError("上传文件失败");
        isLoading.value = false
        throw error;
    } finally {
        isLoading.value = false;
    }
}
// 上传前校检格式和大小
const handleBeforeUpload = (file: any) => {
    // 校检文件类型
    if (props.fileType.length) {
        const fileName = file.name.split('.');
        const fileExt = fileName[fileName.length - 1];
        const isTypeOk = props.fileType.indexOf(fileExt) >= 0;
        if (!isTypeOk) {
            proxy?.$modal.msgError(`文件格式不正确, 请上传${props.fileType.join("/")}格式文件!`);
            return false;
        }
    }
    // 校检文件大小
    if (props.fileSize) {
        const isLt = file.size / 1024 / 1024 <= props.fileSize;
        if (!isLt) {
            proxy?.$modal.msgError(`上传文件大小不能超过 ${props.fileSize} MB!`);
            return false;
        }
    }

    isLoading.value = true
    // proxy?.$modal.loading("正在上传文件，请稍候...");
    number.value++;
    return true;
}

// 文件个数超出
const handleExceed = () => {
    proxy?.$modal.msgError(`上传文件数量不能超过 ${props.limit} 个!`);
}

// 上传失败
const handleUploadError = () => {
    proxy?.$modal.msgError("上传文件失败");
}

// 上传成功回调
const handleUploadSuccess = (res: any, file: UploadFile) => {
    if (res.code === 200) {
        uploadList.value.push({ name: res.data.fileName, url: res.data.url, ossId: res.data.ossId, size: (file.size / 1024 / 1024).toFixed(1) });
        uploadedSuccessfully();
    } else {
        number.value--;
        // proxy?.$modal.closeLoading();
        isLoading.value = false
        proxy?.$modal.msgError(res.msg);
        fileUploadRef.value?.handleRemove(file);
        uploadedSuccessfully();
    }
}

// 删除文件
const handleDelete = (index: number) => {
    fileList.value.splice(index, 1);
    emit("update:modelValue", getPicByfullPath(fileList.value));
}

// 图片全路径转成半路径
const getPicByfullPath = (list: any[]) => {
    if (list.length > 0) {
        const updatedList = list.map((item: any) => {
            return item.url.split(import.meta.env.VITE_APP_PIC_URL)[1];
        });
        return updatedList.join(',');
    } else {
        return '';
    }
}

// 上传结束处理
const uploadedSuccessfully = () => {
    if (number.value > 0 && uploadList.value.length === number.value) {
        fileList.value = fileList.value.filter(f => f.url !== undefined).concat(uploadList.value);
        uploadList.value = [];
        number.value = 0;
        emit("update:modelValue", getPicByfullPath(fileList.value));
        // proxy?.$modal.closeLoading();
        isLoading.value = false
    }
}

// 获取文件名称
const getFileName = (name: string) => {
    // 如果是url那么取最后的名字 如果不是直接返回
    if (name.lastIndexOf("/") > -1) {
        return name.slice(name.lastIndexOf("/") + 1);
    } else {
        return name;
    }
}

// 预览
const handlePictureCardPreview = (file: any) => {
    if (isPdf(file)) {
        window.open(import.meta.env.VITE_APP_PREVIEW_URL + file.url.split(import.meta.env.VITE_APP_PIC_URL)[1], '_blank');
    } else {
        dialogImageUrl.value = file.url;
        dialogVisible.value = true;
    }
}
/** 下载 */
const downloads = async (imgUrl: any) => {
    const response = await fetch(imgUrl.url)
    const blob = await response.blob()
    // 创建下载链接
    const url = window.URL.createObjectURL(blob)
    const link = document.createElement('a')
    link.href = url
    link.download = imgUrl.name
    document.body.appendChild(link)
    link.click()
    document.body.removeChild(link)
    // 释放 Blob URL
    window.URL.revokeObjectURL(url)
}
const isPdf = (fit: any) => {
    return fit.name.includes(".pdf")
}
</script>

<style scoped lang="scss">
.dragge_box {
    display: contents;
    align-items: center;
    flex-wrap: wrap;
}

.size300 {
    width: 298px;
    height: 178px;
}

.size200 {
    width: 198px;
    height: 148px;
}

.size100 {
    width: 80px;
    height: 80px;
}

.sizeinput300 {
    width: 298px;
}

.sizeinput200 {
    width: 198px;
}

.upload-file {
    display: flex;
    align-items: center;
    flex-wrap: wrap;

    .paste_div {
        width: 100%;

        .paste_input {
            margin-bottom: 10px;
        }
    }

    .upload_home {
        margin: 0 8px 8px 0;

        .upload_box {

            display: flex;
            flex-flow: column;
            align-items: center;
            justify-content: center;
            padding: 10px;

            .upload_box_icon {
                color: var(--el-text-color-regular);
                font-size: 50px;
            }

            .upload_box_text {
                color: var(--el-text-color-regular);
                font-size: 12px;
                text-align: center;

                em {
                    color: var(--el-color-primary);
                    font-style: normal;
                }
            }

            .upload_box_tip {
                color: var(--el-text-color-regular);
                font-size: 12px;
                text-align: center;
                line-height: 24px;
            }
        }
    }

}

:deep(.el-upload-dragger) {
    padding: 0;
}

.upload-file-list .el-upload-list__item {
    border: 1px solid #e4e7ed;
    line-height: 2;
    margin-bottom: 10px;
    position: relative;
}

.upload-file-list .ele-upload-list__item-content {
    display: flex;
    justify-content: space-between;
    align-items: center;
    color: inherit;
}

.ele-upload-list__item-content-action .el-link {
    margin-right: 10px;
}

.styleDisplay {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
}

.styleDisplays {
    display: flex;
    align-items: center;
    position: relative;
    margin: 0 8px 8px 0;

    .styleDisplays_items {
        width: 80px;
        height: 80px;
        border: 1px dashed #AFB6C3;
        background-color: rgba(245, 247, 250);
        display: flex;
        align-items: center;
        justify-content: center;
    }

    .preview_pdf {
        border: 1px dashed #AFB6C3;
        border-radius: 5px;
        padding: 5px;
        display: flex;
        align-items: center;
        justify-content: center;
        flex-wrap: wrap;
        align-content: center;

        img {
            width: 60px;
            height: 60px;
            margin-right: 15px;
        }

        .preview_pdf_text {
            color: var(--el-text-color-regular);
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
            width: 100%;
            text-align: center;
        }
    }

    .preview {
        border-radius: 5px;
        border: 1px dashed #AFB6C3;
    }

    .delete {
        position: absolute;
        right: 5px;
        top: 5px;
        z-index: 5;
        width: 20px;
        height: 20px;
        cursor: pointer;
    }

    .quanping {
        position: absolute;
        right: 5px;
        bottom: 5px;
        z-index: 5;
        width: 20px;
        height: 20px;
        cursor: pointer;
    }

    .quanpings {
        position: absolute;
        right: 5px;
        bottom: 5px;
        z-index: 5;
        cursor: pointer;
        color: #0094ff;
    }

    .download {
        position: absolute;
        width: 100%;
        cursor: pointer;
        display: flex;
        align-items: center;
        justify-content: center;

        .downloadpic {
            width: 14px;
            height: 14px;
        }

        .downloadtitle {
            color: #0094FF;
            font-size: 14px;
        }
    }
}
</style>